/* 
 * File:   AllocatorStlType.h
 * Author: root
 *
 * Created on 6 listopad 2011, 11:17
 */

#ifndef ALLOCATORSTLTYPE_H
#define	ALLOCATORSTLTYPE_H

#include <memory>

using std::size_t;
using std::ptrdiff_t;

/*
 STL type allocator interface
 */
  template<typename _Tp>
    class AllocatorStlType
    {
    public:
      typedef size_t     size_type;
      typedef ptrdiff_t  difference_type;
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;
      typedef _Tp&       reference;
      typedef const _Tp& const_reference;
      typedef _Tp        value_type;

      template<typename _Tp1>
        struct rebind
        { typedef AllocatorStlType<_Tp1> other; };

      AllocatorStlType() throw() { }

      AllocatorStlType(const AllocatorStlType&) throw() { }

      template<typename _Tp1>
        AllocatorStlType(const AllocatorStlType<_Tp1>&) throw() { }

      //template <class U>
      //AllocatorStlType& operator=(const AllocatorStlType<U>&) throw();

      ~AllocatorStlType() throw() { }

      pointer
      address(reference __x) const { return &__x; }

      const_pointer
      address(const_reference __x) const { return &__x; }

      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      pointer
      allocate(size_type __n, const void* = 0)
      {
	if (__n > this->max_size())
	  std::__throw_bad_alloc();

	return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
      deallocate(pointer __p, size_type)
      { ::operator delete(__p); }

      size_type
      max_size() const throw()
      { return size_t(-1) / sizeof(_Tp); }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_] allocator::construct
      void
      construct(pointer __p, const _Tp& __val)
      { ::new((void *)__p) _Tp(__val); }


      void
      destroy(pointer __p) { __p->~_Tp(); }
    };

  template<typename _Tp>
    inline bool
    operator==(const AllocatorStlType<_Tp>&, const AllocatorStlType<_Tp>&)
    { return true; }
  
  template<typename _Tp>
    inline bool
    operator!=(const AllocatorStlType<_Tp>&, const AllocatorStlType<_Tp>&)
    { return false; }

#endif	/* AllocatorStlType_H */

